package cn.net.mugui.net.pc.task;

import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.zip.InflaterOutputStream;

import org.bouncycastle.util.encoders.Hex;

import com.alibaba.fastjson.JSONArray;
import com.mugui.base.base.Autowired;
import com.mugui.base.base.Component;
import com.mugui.base.client.net.auto.AutoTask;
import com.mugui.base.client.net.base.Task;
import com.mugui.base.client.net.task.TaskImpl;
import com.mugui.bean.JsonBean;

import cn.net.mugui.net.pc.bean.Barrage;
import cn.net.mugui.net.pc.bean.INTERACT_WORDBean;
import cn.net.mugui.net.pc.bean.NOTICE_MSGBean;
import cn.net.mugui.net.pc.bean.TMDataBean;
import cn.net.mugui.net.pc.panel.comp.TMWindows;
import cn.net.mugui.net.pc.task.RoomDataBean.RoomWsDataBean;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import okio.ByteString;

@AutoTask
@Task
@Component
public class TMBiliTask extends TaskImpl {

	@Autowired
	private TMWsHandle wshandle;

	/**
	 * #opcode 2 客户端发送的心跳包<br>
	 * 3 人气值，数据不是JSON，是4字节整数<br>
	 * 5 命令，数据中['cmd']表示具体命令<br>
	 * 7 认证并加入房间<br>
	 * 8 服务器发送的心跳包<br>
	 */

	public static class TMHead {
		public TMHead(byte[] date, int opcode) {
			this.date = date;
			this.opcode = opcode;
			bag_size = date.length + 16;
		}

		int bag_size;
		byte[] head_len = new byte[] { 0, 16 };
		byte[] version = new byte[] { 0, 1 };
		int opcode;
		int sequence = 1;
		byte date[];

		public ByteString toByteString() {
			ByteBuffer put = ByteBuffer.allocate(bag_size).putInt(bag_size).put(head_len).put(version).putInt(opcode)
					.putInt(sequence).put(date);
			ByteString byteString = new ByteString(put.array());

			return byteString;
		}
	}

	/**
	 * { "uid":6548442, "roomid":22622535, "protover":3, "platform":"web", "type":2,
	 * "key":"T9X4iUjDEawpN0zDol4G5xRSuPTYET7_JTRxilEqwBumFkcM2F-RDfGqGCI5I_ITnsq02xYblsPm0TFobITlo-8419R7HFa6fCX_1ILJuRgx1GFbZdhaqXq7XfoSQ12Xi7GqOwiOGlRKJGwVJMZf4U068w=="
	 * }
	 * 
	 * @author mugui
	 *
	 */
	@Getter
	@Setter
	@Accessors(chain = true)
	public static class Certification extends JsonBean {

		public Certification(String key) {
			this.key = key;
		}

		private long uid = 0;
		private long roomid = TMBiliTask.roomid;
		private int protover = 1;
		private String platform = "web";
		private int type = 2;
//		private String clientver = "1.4.0";
		private String key = null;
	}

	RoomDataBean roomdata = null;

	@Override
	public void init() {
	
		super.init();
	}
	
	public void start() {
		roomdata = HttpRoomData.httpGetConf((int) roomid);
		Iterator<RoomWsDataBean> iterator = roomdata.getHost_list().iterator();
		String wss = null;
		while (iterator.hasNext()) {
			RoomWsDataBean next = RoomWsDataBean.newBean(RoomWsDataBean.class, iterator.next());
			wss = "wss://" + next.getHost() + "/sub";
			break;
		}
		HashMap<String, String> heand = new HashMap<>();
		heand.put("User-Agent",
				"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36");

		WSUtil.ws(wss, heand, wshandle);
	}
	public void stop() {
		wshandle.getSocket().cancel();
	}
	

	@Setter
	private static long roomid = 6517995;
//	@Setter
//	private static long roomid = 271744;
//	@Setter
//	private static long roomid = 22625025;

	@Override
	public void run() {
//		while (true) {
//			try {
//				handle();
//			} catch (Exception e) {
//				e.printStackTrace();
//			}
//			Other.sleep(3000);
//		}
	}

	private void handle() {
		// 读取弹幕消息
//		readTMMsg();
	}

	/**
	 * https://api.live.bilibili.com/xlive/web-room/v1/dM/gethistory?roomid=6517995
	 */
//	private void readTMMsg() {
//
//	}

	long update_time = System.currentTimeMillis();

	public void WsHandle(ByteString byteString) {
		if (System.currentTimeMillis() - update_time >= 30 * 1000) {
			TMHead tmHead = new TMHead("[object Object]".getBytes(), 2);
			wshandle.getSocket().send(tmHead.toByteString());
			update_time = System.currentTimeMillis();
		}
		ByteBuffer message = byteString.asByteBuffer();
		int length = message.getInt();
		short len = message.getShort();
		short code1 = message.getShort();
		int code = message.getInt();
		int base = message.getInt();
		byte[] bytes = new byte[(int) (length - len)];
		message.get(bytes);
		/**
		 * 2 客户端发送的心跳包 3 人气值，数据不是JSON，是4字节整数 5 命令，数据中['cmd']表示具体命令 7 认证并加入房间 8 服务器发送的心跳包
		 */
		switch (code1) {
		case 0:// 字符串
			switch (code) {
			case 5:
				String string = new String(bytes);
				handleTMData(TMDataBean.newBean(TMDataBean.class,string));
				break;
			default:
				break;
			}
			break;
		case 1:// int型
			switch (code) {
			case 3:
				BigInteger bigInteger = new BigInteger(Hex.toHexString(bytes), 16);
				System.out.println("人气值：" + bigInteger);
				break;
			default:
				break;
			}
			break;
		case 2:// 压缩json数据
			switch (code) {
			case 5:
				byte[] bytesTozlibInflate = BytesTozlibInflate(bytes);
				try {
					handle_zlibMessage(bytesTozlibInflate);
//					String string = new String(bytesTozlibInflate);
//					System.out.println("解析数据：" + string);
				} catch (Exception e) {
					e.printStackTrace();
				}

				break;
			default:
				break;
			}
			break;
		default:
			break;
		}

	}

	/**
	 * 处理解压后子数据包
	 * 
	 * @param bytes
	 */
	@SuppressWarnings("unused")
	public void handle_zlibMessage(byte[] data) throws Exception {
		ByteBuffer message = ByteBuffer.wrap(data);
		while (true) {
			if (message.limit() - message.position() < 4) {
				break;
			}
			int length = message.getInt();
			short len = message.getShort();
			short code1 = message.getShort();
			int code = message.getInt();
			int base = message.getInt();
			byte[] bytes = new byte[(int) (length - len)];
			message.get(bytes);
			System.out.println("code1=" + code1 + "        code=" + code);
			/**
			 * 2 客户端发送的心跳包 3 人气值，数据不是JSON，是4字节整数 5 命令，数据中['cmd']表示具体命令 7 认证并加入房间 8 服务器发送的心跳包
			 */
			switch (code1) {
			case 0:// 字符串
				switch (code) {
				case 5:
					String string = new String(bytes);
					TMDataBean newBean = TMDataBean.newBean(TMDataBean.class, string);
					handleTMData(newBean);
					break;
				default:
					break;
				}
				break;
			case 1:// int型
				switch (code) {
				case 3:
					BigInteger bigInteger = new BigInteger(Hex.toHexString(bytes), 16);
					System.out.println("人气值：" + bigInteger);
					break;
				default:
					break;
				}
				break;
			case 2:// 压缩json数据
				switch (code) {
				case 5:
					byte[] bytesTozlibInflate = BytesTozlibInflate(bytes);
					try {
						String string = new String(bytesTozlibInflate);
						System.out.println("无法处理数据：" + string);
					} catch (Exception e) {
						e.printStackTrace();
					}

					break;
				default:
					break;
				}
				break;
			default:
				break;
			}

		}

	}

	private void handleTMData(TMDataBean newBean) {

		System.out.println("handleTMData->" + newBean);
		// 舰长进入直播间消息
		switch (newBean.getCmd()) {
		case "ENTRY_EFFECT":
			System.out.println(newBean.getData());
			break;
		// msg_type 1 为进入直播间 2 为关注 3为分享直播间
		case "INTERACT_WORD":
			INTERACT_WORDBean word = INTERACT_WORDBean.newBean(INTERACT_WORDBean.class, newBean.getData());
//			System.out.println(word.getUname()+"进入直播间");
			windws.addMsg(word);
			break;
		// 节奏风暴推送 action 为start和end
		case "SPECIAL_GIFT":
//			LOGGER.debug("节奏风暴推送:::" + message);
			break;
		case "DANMU_MSG":// 弹幕消息
		{
			System.out.println("DANMU_MSG:" + newBean.getInfo());
			String[] array = newBean.getInfo();

			JSONArray user_ = JSONArray.parseArray(array[2]);
			JSONArray msg_type = JSONArray.parseArray(array[0]);
			JSONArray medal_ = JSONArray.parseArray(array[3]);
			JSONArray ulevel = JSONArray.parseArray(array[4]);
			JSONArray title = JSONArray.parseArray(array[5]);

			Barrage barrage = Barrage.getBarrage(user_.getLong(0), user_.getString(1), array[1], msg_type.getShort(9),
					msg_type.getLong(4), user_.getShort(2), user_.getShort(3), user_.getShort(4), user_.getInteger(5),
					user_.getShort(6), medal_.size() <= 0 ? 0 : medal_.getShort(0),
					medal_.size() <= 0 ? "" : medal_.getString(1), medal_.size() <= 0 ? "" : medal_.getString(2),
					medal_.size() <= 0 ? 0L : medal_.getLong(3), ulevel.getShort(0), ulevel.getString(3),
					title.getString(0), title.getString(1),Short.parseShort(array[7]));
			windws.addMsg(barrage);
		}
			break;

		// 送普通礼物
		case "SEND_GIFT":
			break;

		// 部分金瓜子礼物连击
		case "COMBO_SEND":
			break;

		// 上舰
		case "GUARD_BUY":
			break;

		// 上舰消息推送
		case "GUARD_LOTTERY_START":
			break;

		// 上舰抽奖消息推送
		case "USER_TOAST_MSG":
//				LOGGER.debug("上舰抽奖消息推送:::" + message);
			break;
		// 醒目留言日文翻译
		case "SUPER_CHAT_MESSAGE_JPN":
//			LOGGER.debug("醒目留言日文翻译消息推送:::" + message);
			break;
		// 醒目留言
		case "SUPER_CHAT_MESSAGE":
			break;
		// 删除醒目留言
		case "SUPER_CHAT_MESSAGE_DELETE":
//			LOGGER.debug("该条醒目留言已被删除:::" + message);
			break;

		// 欢迎老爷进来本直播间
		case "WELCOME":
			break;

		// 欢迎舰长进入直播间
		case "WELCOME_GUARD":
			break;

		// 禁言消息
		case "ROOM_BLOCK_MSG":
			break;
		// 本主播在本分区小时榜排名更新推送 不会更新页面的排行显示信息
		case "ACTIVITY_BANNER_UPDATE_V2":
//			LOGGER.debug("小时榜消息更新推送:::" + message);
			break;
		// 本房间分区修改
		case "ROOM_CHANGE":
//			LOGGER.debug("房间分区已更新:::" + message);
			break;
		// 本房间分区排行榜更新 更新页面的排行显示信息
		case "ROOM_RANK":
			break;

		// 推测为获取本小时榜榜单第一名主播的信息 推测激活条件为本直播间获得第一
		case "new_anchor_reward":
//				LOGGER.debug("获取本小时榜榜单第一名主播的信息:::" + message);
			break;

		// 小时榜榜单信息推送 推测激活条件为本直播间获得第一
		case "HOUR_RANK_AWARDS":
//				LOGGER.debug("恭喜xxxx直播间获得:::" + message);
			break;

		// 直播间粉丝数更新 经常
		case "ROOM_REAL_TIME_MESSAGE_UPDATE":
			break;

		// 直播间许愿瓶消息推送更新
		case "WISH_BOTTLE":
//				LOGGER.debug("直播间许愿瓶消息推送更新:::" + message);
			break;

		// 广播小电视类抽奖信息推送,包括本房间的舰长礼物包括,本直播间所在小时榜榜单主播信息的推送 需要unicode转义 免费辣条再见！！！！
		case "NOTICE_MSG":
//				message = ByteUtils.unicodeToString(message);
//				LOGGER.debug("小电视类抽奖信息推送:::" + message);
			
			NOTICE_MSGBean notice_MSGBean = NOTICE_MSGBean.newBean(NOTICE_MSGBean.class, newBean.get());
//			System.out.println(word.getUname()+"进入直播间");
			windws.addMsg(notice_MSGBean);
			
			
			break;

		// 本房间开启活动抽奖(33图,小电视图,任意门等) 也指本房间内赠送的小电视 摩天大楼类抽奖
		case "RAFFLE_START":
//				LOGGER.debug("本房间开启了活动抽奖:::" + message);
			break;

		// 本房间活动中奖用户信息推送 也指抽奖结束
		case "RAFFLE_END":
//				LOGGER.debug("看看谁是幸运儿:::" + message);
			break;

		// 本房间天选时刻结束
		case "ANCHOR_LOT_END":
//				LOGGER.debug("本房间天选时刻结束:::" + message);
			break;

		// 本房间天选时刻获奖信息推送
		case "ANCHOR_LOT_AWARD":
//				LOGGER.debug("本房间天选时刻中奖用户是:::" + message);
			break;

		// 获得推荐位推荐消息
		case "ANCHOR_NORMAL_NOTIFY":
//				LOGGER.debug("本房间获得推荐位:::" + message);				
			break;
		// 周星消息推送
		case "WEEK_STAR_CLOCK":
//		        LOGGER.debug("周星消息推送:::" + message);
			break;

		// 推测本主播周星信息更新
		case "ROOM_BOX_MASTER":
//				LOGGER.debug("周星信息更新:::" + message);
			break;

		// 周星消息推送关闭
		case "ROOM_SKIN_MSG":
//				LOGGER.debug("周星消息推送关闭:::" + message);
			break;

		// 中型礼物多数量赠送消息推送 例如b克拉 亿元
		case "SYS_GIFT":
//				LOGGER.debug("中型礼物多数量赠送消息推送:::" + message);
			break;

		// lol活动礼物？？？
		case "ACTIVITY_MATCH_GIFT":
//				LOGGER.debug("lol专属房间礼物赠送消息推送:::" + message);
			break;

//----------------------------------------pk信息多为要uicode解码-------------------------------------------------
		// 推测为房间pk信息推送
		case "PK_BATTLE_ENTRANCE":
//		        LOGGER.debug("房间pk活动信息推送:::" + message);
			break;

		// 活动pk准备
		case "PK_BATTLE_PRE":
//		        LOGGER.debug("房间活动pk准备:::" + message);
			break;

		// 活动pk开始
		case "PK_BATTLE_START":
//		        LOGGER.debug("房间活动pk开始:::" + message);
			break;

		// 活动pk中
		case "PK_BATTLE_PROCESS":
//		        LOGGER.debug("房间活动pk中:::" + message);
			break;

		// 活动pk详细信息
		case "PK_BATTLE_CRIT":
//		        LOGGER.debug("房间活动pk详细信息推送:::" + message);
			break;

		// 活动pk类型推送
		case "PK_BATTLE_PRO_TYPE":
//		        LOGGER.debug("房间活动pk类型推送:::" + message);
			break;

		// 房间活动pk结束
		case "PK_BATTLE_END":
//		        LOGGER.debug("房间pk活动结束::" + message);
			break;

		// 活动pk结果用户 推送
		case "PK_BATTLE_SETTLE_USER":
//		        LOGGER.debug("活动pk结果用户 推送::" + message);	
			break;

		// 活动pk礼物开始 1辣条
		case "PK_LOTTERY_START":
//		        LOGGER.debug("活动pk礼物开始 推送::" + message);			
			break;

		// 活动pk结果房间
		case "PK_BATTLE_SETTLE":
//		        LOGGER.debug("活动pk结果房间推送::" + message);
			break;

		// pk开始
		case "PK_START":
//				LOGGER.debug("房间pk开始:::" + message);
			break;

		// pk准备中
		case "PK_PRE":
//				LOGGER.debug("房间pk准备中:::" + message);
			break;

		// pk载入中
		case "PK_MATCH":
//				LOGGER.debug("房间pk载入中:::" + message);
			break;

		// pk再来一次触发
		case "PK_CLICK_AGAIN":
//				LOGGER.debug("房间pk再来一次:::" + message);			
			break;
		// pk结束
		case "PK_MIC_END":
//				LOGGER.debug("房间pk结束:::" + message);	
			break;

		// pk礼物信息推送 激活条件推测为pk胜利 可获得一个辣条
		case "PK_PROCESS":
//				LOGGER.debug("房间pk礼物推送:::" + message);				
			break;

		// pk结果信息推送
		case "PK_SETTLE":
//				LOGGER.debug("房间pk结果信息推送:::" + message);					
			break;

		// pk结束信息推送
		case "PK_END":
//				LOGGER.debug("房间pk结束信息推送:::" + message);					
			break;

		// 系统信息推送
		case "SYS_MSG":
//				LOGGER.debug("系统信息推送:::" + message);					
			break;

		// 总督登场消息
		case "GUARD_MSG":
//				LOGGER.debug("总督帅气登场:::" + message);
			break;

		// 热门房间？？？？广告房间？？ 不知道这是什么 推测本直播间激活 目前常见于打广告的官方直播间 例如手游 碧蓝航线 啥的。。
		case "HOT_ROOM_NOTIFY":
//				LOGGER.debug("热门房间推送消息:::" + message);
			break;

		// 小时榜面板消息推送
		case "PANEL":
//				LOGGER.debug("热小时榜面板消息推送:::" + message);	
			break;

		// 星之耀宝箱使用 n
		case "ROOM_BOX_USER":
//				LOGGER.debug("星之耀宝箱使用:::" + message);
			break;

		// 语音加入？？？？ 暂不知道
		case "VOICE_JOIN_ROOM_COUNT_INFO":
//				LOGGER.debug("语音加入:::" + message);
			break;

		// 语音加入list？？？？ 暂不知道
		case "VOICE_JOIN_LIST":
//				LOGGER.debug("语音加入list:::" + message);
			break;

		// lol活动
		case "LOL_ACTIVITY":
//				LOGGER.debug("lol活动:::" + message);
			break;

		// 队伍礼物排名 目前只在6号lol房间抓取过
		case "MATCH_TEAM_GIFT_RANK":
//				LOGGER.debug("队伍礼物排名:::" + message);		
			break;

		// 6.13端午节活动粽子新增活动更新命令 激活条件有人赠送活动礼物
		case "ROOM_BANNER":
//				LOGGER.debug("收到活动礼物赠送，更新信息:::" + message);	
			break;

		// 设定房管消息 新房管的诞生
		case "room_admin_entrance":
//				LOGGER.debug("有人被设为了房管:::" + message);
			break;

		// 房管列表更新消息 激活条件为新房管的诞生
		case "ROOM_ADMINS":
//				LOGGER.debug("房管列表更新推送:::" + message);	
			break;

		// 房间护盾 推测推送消息为破站官方屏蔽的关键字 触发条件未知
		case "ROOM_SHIELD":
//				LOGGER.debug("房间护盾触发消息:::" + message);
			break;

		// 主播开启房间全局禁言
		case "ROOM_SILENT_ON":
//				LOGGER.debug("主播开启房间全局禁言:::" + message);
			break;

		// 主播关闭房间全局禁言
		case "ROOM_SILENT_OFF":
//				LOGGER.debug("主播关闭房间全局禁言:::" + message);
			break;

		// 主播状态检测 直译 不知道什么情况 statue 1 ，2 ，3 ，4
		case "ANCHOR_LOT_CHECKSTATUS":
//				LOGGER.debug("主播房间状态检测:::" + message);
			break;

		// 房间警告消息 目前已知触发条件为 房间分区不正确
		case "WARNING":
//				LOGGER.debug("房间警告消息:::" + message);
			break;
		// 直播开启
		case "LIVE":
//				LOGGER.debug("直播开启:::" + message);
			break;

		// 直播超管被切断
		case "CUT_OFF":
//				LOGGER.debug("很不幸，本房间直播被切断:::" + message);	
			break;

		// 本房间已被封禁
		case "ROOM_LOCK":
//				LOGGER.debug("很不幸，本房间已被封禁:::" + message);	
			break;

		// 直播准备中(或者是关闭直播)
		case "PREPARING":

//				LOGGER.debug("直播准备中(或者是关闭直播):::" + message);
			break;

		// 勋章亲密度达到上每日上限通知
		case "LITTLE_TIPS":
//				LOGGER.debug("勋章亲密度达到上每日上限:::" + message);		
			break;

		default:
			System.out.println(newBean.getData());
			break;
		}
	}

	@Autowired
	private TMWindows windws;

	/**
	 * byte[]的zlib解压
	 * 
	 * @param bs 待解压byte数组
	 * @return b 解压完成的byte[]
	 */
	public static byte[] BytesTozlibInflate(byte[] bs) {
		byte[] b = null;
		try {
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			InflaterOutputStream zos = new InflaterOutputStream(bos);
			zos.write(bs);
			zos.close();
			b = bos.toByteArray();
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return b;
	}

	public void WsHandle(String text) {

		System.out.println(text);
	}

	public void WsInit() {
		Certification cert = new Certification(roomdata.getToken());
		TMHead tmHead = new TMHead(cert.toString().getBytes(), 7);
		wshandle.getSocket().send(tmHead.toByteString());

		tmHead = new TMHead("[object Object]".getBytes(), 2);
		wshandle.getSocket().send(tmHead.toByteString());
		update_time = System.currentTimeMillis();

//		Certification cert = new Certification(roomdata.getToken());
//		TMHead tmHead = new TMHead(cert.toString().getBytes(), 7);
//		websocket.send(tmHead.toByteString().asByteBuffer());
//		
//		 tmHead = new TMHead("[object Object]".getBytes(),2);
//		websocket.send(tmHead.toByteString().asByteBuffer());

	}

//	public void WsHandle(ByteBuffer message) {
//
//		System.out.println(message);
//		int length = message.getInt();
//		short len = message.getShort();
//		short code1 = message.getShort();
//		int code = message.getInt();
//		int base = message.getInt();
//		byte[] bytes = new byte[(int) (length - len)];
//		message.get(bytes);
//		String string = new String(bytes);
//		System.out.println(string);
//		if (code == 8) {
//
//		}
//	}

}
